/**
 * @file tcp_socket_client.cpp
 * @brief 继承于QTcpSocket，实现连接管理如自动重连、掉线检测
 */
#include "tcp_socket_client.h"
#include <QTimer>

namespace infrastructure {
namespace io {

TcpSocketClient::TcpSocketClient(QObject *parent)
    : QTcpSocket(parent)
{
}

TcpSocketClient::TcpSocketClient(qintptr socketDescriptor, QObject *parent)
    : QTcpSocket(parent), socketID(socketDescriptor)
{
    this->setSocketDescriptor(socketDescriptor);
    dis = connect(this, &QTcpSocket::disconnected, [&](){
        emit sig_sockDisConnect(socketID, this->peerAddress().toString(), this->peerPort(), QThread::currentThread());
        this->deleteLater();
    });
}

TcpSocketClient::~TcpSocketClient()
{
    this->disconnectFromHost();
    if (this->state() != QAbstractSocket::UnconnectedState) {
        this->waitForDisconnected();
    }
}

void TcpSocketClient::onCheckState()
{
    switch (this->state()) {
    case QAbstractSocket::UnconnectedState:
        reConnect();
        break;
    case QAbstractSocket::HostLookupState:
    case QAbstractSocket::ConnectingState:
    case QAbstractSocket::ConnectedState:
    case QAbstractSocket::BoundState:
    case QAbstractSocket::ListeningState:
    case QAbstractSocket::ClosingState:
        break;
    }
}

void TcpSocketClient::onErr(QAbstractSocket::SocketError error)
{
    Q_UNUSED(error);
    // 3秒后自动重连
    QTimer::singleShot(3000, this, &TcpSocketClient::reConnect);
}

bool TcpSocketClient::initConnection(const QHostAddress &address, quint16 port)
{
    m_remoteIp = address;
    m_remotePort = port;

    QObject::connect(this, &TcpSocketClient::connected, this, &TcpSocketClient::slotConnected);
    QObject::connect(this, &QAbstractSocket::errorOccurred, this, &TcpSocketClient::onErr);
    this->connectToHost(m_remoteIp, m_remotePort);
    return true;
}

void TcpSocketClient::resetConnection(const QHostAddress& address, quint16 port)
{
    m_remoteIp = address;
    m_remotePort = port;

    this->disconnectFromHost();
    this->close();
    this->abort();
    this->connectToHost(m_remoteIp, m_remotePort);
}

void TcpSocketClient::slotConnected()
{
    // 连接成功的回调
}

void TcpSocketClient::disConTcp(qint64 socketDescriptor)
{
    if (socketDescriptor == socketID) {
        this->disconnectFromHost();
    } else if (socketDescriptor == -1) { // -1为全部断开
        disconnect(dis); // 先断开连接的信号槽，防止二次析构
        this->disconnectFromHost();
        this->deleteLater();
    }
}

void TcpSocketClient::reConnect()
{
    this->abort();
    this->connectToHost(m_remoteIp, m_remotePort);
}

void TcpSocketClient::tcpClientDisConnected()
{
    // TCP客户端断开连接
}

} // namespace io
} // namespace infrastructure
